package com.tmt.helper;

import com.tmt.annotation.parser.EnumAnnotationParser;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Created by ThreeManTeam on 2017/5/25.
 */
public class StringHelper {

    public static List<String> BooleanValueList = new ArrayList<>();

    static {
        BooleanValueList.addAll(Arrays.asList("true", "yes", "checked", "on"));
    }

    ;

    /**
     * 字符串是否为空
     *
     * @param str 需要判断的字符串
     * @return 是否为空
     */
    public static boolean isEmpty(String str) {
        return str == null || "".equals(str.trim());
    }


    public static String[] splitWithoutEmpty(String target, String regex) {
        return Arrays.asList(target.split(regex)).stream().filter(x -> x != null && x.length() > 0).map(String::trim).toArray(String[]::new);
    }

    public static String upperFirst(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    public static String lowerFirst(String name) {
        return name.substring(0, 1).toLowerCase() + name.substring(1);
    }

    /**
     * 字符串组合中忽略大小写包含某个字符串。
     * <pre>
     * containsIgnoreCase(Arrays.asList("a", "b", "c"), "A"); // true
     * containsIgnoreCase(Arrays.asList("a", "b", "c"), "b"); // true
     * containsIgnoreCase(Arrays.asList("a", "b", "c"), "d"); // false
     * </pre>
     *
     * @param list 候选集合
     * @param str  特定字符串
     * @return 是否包含
     */
    public static boolean containsIgnoreCase(List<String> list, String str) {
        if (list == null || str == null)
            return false;

        for (String temp : list) {
            if (temp != null && temp.equalsIgnoreCase(str)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 字符串是否包含列表内的所有字符串。
     * <pre>
     * containsAll("abc", Arrays.asList("a", "b")); // true
     * containsAll("abc", Arrays.asList("a", "d")); // false
     * </pre>
     *
     * @param str         需要判断的字符串
     * @param containList 判定的子元素
     * @return 是否包含所有子元素
     */
    public static boolean containsAll(String str, List<String> containList) {
        if (str == null || containList == null)
            return false;

        for (String temp : containList) {
            if (temp != null && !str.contains(temp)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 类型转换， 枚举中只支持 string 转枚举
     *
     * @param obj   需要转换的对象
     * @param clazz 需要转换到的目标类型
     * @param <T>   目标类型
     * @return 转换后的结果
     */
    @SuppressWarnings("all")
    public static <T> T convertTo(Object obj, Class<T> clazz) {
        if (obj == null || clazz == null)
            return null;

        if (obj.getClass() == clazz
                || obj.getClass().getSimpleName().toLowerCase().equals(clazz.getSimpleName().toLowerCase()))
            return (T) obj;

        if (clazz == String.class) {
            Class objCls = obj.getClass();
            if (objCls.isEnum()) {
                return (T) ((Enum) obj).name();
            }
            if (objCls == Boolean.class || objCls == boolean.class) {
                return (T) (((Boolean) obj) == true ? "true" : "false");
            }
            if (objCls == Date.class) {
                return (T) DateHelper.formatDate((Date) obj, DateHelper.DATE_TIME_FORMAT);
            }
            if (!objCls.isPrimitive())
                return (T) obj.toString();
        }

        String objStr = obj.toString();
        if (clazz == Integer.class || clazz == int.class) {
            return (T) Integer.valueOf(objStr);
        }
        if (clazz == Long.class || clazz == long.class) {
            return (T) Long.valueOf(objStr);
        }
        if (clazz == Byte.class || clazz == byte.class) {
            return (T) Byte.valueOf(objStr);
        }
        if (clazz == Short.class || clazz == short.class) {
            return (T) Short.valueOf(objStr);
        }

        if (clazz == Boolean.class || clazz == boolean.class) {
            return (T) Boolean.valueOf(containsIgnoreCase(BooleanValueList, objStr));
        }
        if (clazz == Float.class || clazz == float.class) {
            return (T) Float.valueOf(objStr);
        }
        if (clazz == Double.class || clazz == double.class) {
            return (T) Double.valueOf(objStr);
        }

        if (clazz == Date.class) {
            return (T) DateHelper.parseDate(objStr);
        }
        if (clazz == BigDecimal.class) {
            return (T) new BigDecimal(objStr);
        }
        if (clazz.isEnum()) {
            return (T) covertToEnum(objStr, clazz.asSubclass(Enum.class));
        }

        if (obj.getClass() == String.class && ((String) obj).trim().equals("")) {
            obj = null;
        }

        return (T) obj;
    }

    public static <X, Y> X stringToList(Object obj, Class<X> clazz, Class<Y> paramClazz) {
        try {
            List<Y> list = new ArrayList<>();

            int count1 = obj.toString().split(";").length;
            int count2 = obj.toString().split(",").length;
            int count3 = obj.toString().split("\\|").length;
            String splitStr = ";";
            if (count2 > count1 && count2 > count3) {
                splitStr = ",";
            } else if (count3 > count1 && count3 > count2) {
                splitStr = "\\|";
            }

            List<String> strList = Arrays.stream(obj.toString().split(splitStr)).filter(x -> x.length() > 0)
                    .collect(Collectors.toList());
            strList.stream().forEach(x -> {
                Object value = StringHelper.convertTo(x, paramClazz);
                list.add((Y) value);
            });

            return (X) list;

        } catch (Exception e) {
        }
        return (X) obj;
    }

    public static <X, Y> X stringArrayToList(String[] obj, Class<X> clazz, Class<Y> paramClazz) {
        List<Y> list = new ArrayList<>();
        Arrays.asList(obj).forEach(x -> list.add(StringHelper.convertTo(x, paramClazz)));
        return (X) list;
    }

    private static <T> T covertToEnum(String obj, Class<T> clazz) {
        T result;
        try {
            result = (T) Enum.valueOf(clazz.asSubclass(Enum.class), obj);
            return result;
        } catch (Exception ex) {
        }

        result = (T) EnumAnnotationParser.convertFromTitle(clazz.asSubclass(Enum.class), obj);
        return result;
    }

    public static String getStandardPriceString(BigDecimal value, String prefix) {
        if (value == null)
            return "";

        String unit = "";
        int scale = 4;
        BigDecimal unitValue = new BigDecimal(10000);
        if (value.compareTo(unitValue) >= 0) {
            unit = "万";
            value = value.divide(unitValue, scale, BigDecimal.ROUND_HALF_UP);
        }

        return (prefix != null && prefix.trim().length() > 0 ? prefix : "")
                + value.setScale(scale, BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString()
                + (unit.length() > 0 ? " " + unit : "");
    }

}
